package json

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"

	"gitee.com/nggs/tools/static_data"

	"gitee.com/nggs/util"
)

//const (
//	typeReplaceName = "tYpE"
//	mapReplaceName  = "mAp"
//)

//var gReplaceNames = map[string]string{
//	"type": typeReplaceName,
//	"map":  mapReplaceName,
//}

type Field struct {
	RawName string `json:"Name"`
	Name    string `json:"-"`
	Type    string
	Comment string
}

type Table struct {
	Package       string
	JsonFileName  string `json:"-"`
	RawName       string `json:"Name"`
	Name          string `json:"-"`
	Fields        []*Field
	UniqueIndexes []*Field `json:",omitempty"` // 唯一索引
	NormalIndexes []*Field `json:",omitempty"` // 普通索引
	Attributes    []*Field `json:",omitempty"`
	Enums         []*static_data.Enum
	Comment       string
	extends       map[string]string
}

func NewTable(pkg string, enums []*static_data.Enum) (t *Table) {
	t = &Table{
		Package: pkg,
		Enums:   enums,
		extends: make(map[string]string),
	}
	return
}

func (t *Table) format(info os.FileInfo, replaceNames map[string]string) (err error) {
	t.JsonFileName = info.Name()
	t.Name = util.FormatFieldName(t.RawName)

	for _, f := range t.Fields {
		f.Name = util.FormatFieldName(f.RawName)
		if replaceName, ok := replaceNames[f.RawName]; ok {
			f.RawName = replaceName
		}
	}

	for _, f := range t.UniqueIndexes {
		f.Name = util.FormatFieldName(f.RawName)
		if replaceName, ok := replaceNames[f.RawName]; ok {
			f.RawName = replaceName
		}
	}

	for _, f := range t.NormalIndexes {
		f.Name = util.FormatFieldName(f.RawName)
		if replaceName, ok := replaceNames[f.RawName]; ok {
			f.RawName = replaceName
		}
	}

	for _, f := range t.Attributes {
		f.Name = util.FormatFieldName(f.RawName)
		if replaceName, ok := replaceNames[f.RawName]; ok {
			f.RawName = replaceName
		}
	}

	return
}

func (t Table) GetExtendContent(name string) (content string) {
	return t.extends[name]
}

func collectExtend(extendBeginRegex *regexp.Regexp, content []byte) (extends []string) {
	begins := extendBeginRegex.FindAll(content, -1)
	for _, b := range begins {
		extend := string(b)
		extend = strings.TrimPrefix(extend, "//<")
		extend = strings.TrimSuffix(extend, ">")
		if extend != "" {
			extends = append(extends, extend)
		}
	}
	return
}

func (t *Table) CollectExtend(filePath string, extendBeginRegex *regexp.Regexp) (err error) {
	err = util.IsDirOrFileExist(filePath)
	if err == nil {
		// 记录下手写的代码
		oldData, err := ioutil.ReadFile(filePath)
		if err != nil {
			return fmt.Errorf("读取[%s]失败, %s", filePath, err)
		}

		old := string(oldData)

		ex := collectExtend(extendBeginRegex, oldData)

		for _, name := range ex {
			beginTag := fmt.Sprintf("//<%s>", name)
			beginIndex := strings.Index(old, beginTag) + len(beginTag)

			endTag := fmt.Sprintf("//</%s>", name)
			endIndex := strings.Index(old, endTag)
			if (beginIndex > -1 && endIndex > -1) && (beginIndex != endIndex) {
				t.extends[name] = old[beginIndex:endIndex]
			}
		}
	}
	return nil
}

//func (t Table) GetTypeField() (tf *Field) {
//	for _, f := range t.Fields {
//		if strings.ToLower(f.RawName) == "type" {
//			tf = f
//			return
//		}
//	}
//	return
//}

type StaticData struct {
	Package string
	Tables  []*Table
	Enums   []*static_data.Enum
	extends map[string]string
}

func New(pkg string) *StaticData {
	return &StaticData{
		Package: pkg,
		extends: map[string]string{},
	}
}

func (s *StaticData) CollectExtend(filePath string, extendBeginRegex *regexp.Regexp) (err error) {
	s.extends = map[string]string{}
	err = util.IsDirOrFileExist(filePath)
	if err == nil {
		// 记录下手写的代码
		oldData, err := ioutil.ReadFile(filePath)
		if err != nil {
			return fmt.Errorf("读取[%s]失败, %s", filePath, err)
		}

		old := string(oldData)

		ex := collectExtend(extendBeginRegex, oldData)

		for _, name := range ex {
			beginTag := fmt.Sprintf("//<%s>", name)
			beginIndex := strings.Index(old, beginTag) + len(beginTag)

			endTag := fmt.Sprintf("//</%s>", name)
			endIndex := strings.Index(old, endTag)
			if (beginIndex > -1 && endIndex > -1) && (beginIndex != endIndex) {
				s.extends[name] = old[beginIndex:endIndex]
			}
		}
	}
	return nil
}

func (s StaticData) GetExtendContent(name string) (content string) {
	return s.extends[name]
}
